package com.gitee.wsl.transform.validator

import kotlin.jvm.JvmInline

/**
 * An error that occurred during validation.
 * Presence of ValidationErrors in the resulting [Input.Invalid] indicates
 * that the value of the input is invalid.
 */
interface ValidationError {

    /**
     * A value that is being validated
     */
     val value: String

    /**
     * A generic validation error that can be subclassed. In this case,
     * you need to keep track of your custom errors yourself.
     */
     open class Generic(
        override val value: String,
    ) : ValidationError

    /**
     * The input is blank.
     * @see pro.respawn.kmmutils.inputforms.default.Rules.NonEmpty
     */
    @JvmInline
     value class Empty(
        override val value: String
    ) : ValidationError

    /**
     * Length of the input was not in [range]
     * @see pro.respawn.kmmutils.inputforms.default.Rules.LengthInRange
     */
     data class NotInRange(
        override val value: String,
         val range: IntRange,
    ) : ValidationError

    /**
     * Length of the input was not exactly [length]
     * @see pro.respawn.kmmutils.inputforms.default.Rules.LengthExact
     */
     data class LengthIsNotExactly(
        override val value: String,
         val length: Int,
    ) : ValidationError

    /**
     * Input was shorter than [minLength]
     * @see pro.respawn.kmmutils.inputforms.default.Rules.LongerThan
     */
     data class TooShort(
        override val value: String,
         val minLength: Int,
    ) : ValidationError

    /**
     * Input was longer than [maxLength]
     * @see pro.respawn.kmmutils.inputforms.default.Rules.ShorterThan
     */
     data class TooLong(
        override val value: String,
         val maxLength: Int,
    ) : ValidationError

    /**
     * Input does not match the [pattern]
     * @see pro.respawn.kmmutils.inputforms.default.Rules.Matches
     */
     data class DoesNotMatch(
        override val value: String,
        val pattern: Regex,
    ) : ValidationError

    /**
     * Input does not start with [prefix]
     * @see pro.respawn.kmmutils.inputforms.default.Rules.StartsWith
     */
     data class DoesNotStartWith(
        override val value: String,
         val prefix: String
    ) : ValidationError

    /**
     * Input does not end with [suffix]
     * @see pro.respawn.kmmutils.inputforms.default.Rules.EndsWith
     */
     data class DoesNotEndWith(
        override val value: String,
         val suffix: String,
    ) : ValidationError

    /**
     * Input does not contain a [needle]
     * @see pro.respawn.kmmutils.inputforms.default.Rules.Contains
     */
     data class DoesNotContain(
        override val value: String,
         val needle: String
    ) : ValidationError

    /**
     * Input is not alpha-numeric
     * @see pro.respawn.kmmutils.inputforms.default.Rules.AlphaNumeric
     */
    @JvmInline
    value class NotAlphaNumeric(
        override val value: String,
    ) : ValidationError

    /**
     * Input has digits
     * @see pro.respawn.kmmutils.inputforms.default.Rules.NoDigits
     */
     data class ContainsDigits(
        override val value: String,
    ) : ValidationError

    /**
     * Input has no digits
     * @see pro.respawn.kmmutils.inputforms.default.Rules.HasDigit
     */
     data class HasNoDigits(
        override val value: String,
    ) : ValidationError

    /**
     * Input has letters
     * @see pro.respawn.kmmutils.inputforms.default.Rules.NoLetters
     */
     data class ContainsLetters(
        override val value: String,
    ) : ValidationError

    /**
     * Input has no letters
     * @see pro.respawn.kmmutils.inputforms.default.Rules.HasLetter
     */
    @JvmInline
     value class HasNoLetters(
        override val value: String
    ) : ValidationError

    /**
     * Input's value was not equal to [other]
     * @see pro.respawn.kmmutils.inputforms.default.Rules.Equals
     */
     data class IsNotEqual(
        override val value: String,
        val other: String
    ) : ValidationError

    /**
     * Input's value contained anything except letters.
     * @see pro.respawn.kmmutils.inputforms.default.Rules.LettersOnly
     */
    @JvmInline
     value class NotLettersOnly(
        override val value: String,
    ) : ValidationError

    /**
     * Input's value contained anything except digits
     * @see pro.respawn.kmmutils.inputforms.default.Rules.DigitsOnly
     */
    @JvmInline
     value class NotDigitsOnly(
        override val value: String
    ) : ValidationError

    /**
     * Input's value is not an ascii symbol
     * @see pro.respawn.kmmutils.inputforms.default.Rules.AsciiOnly
     */
    @JvmInline
     value class NotAscii(
        override val value: String,
    ) : ValidationError

    /**
     * Input's value is not lowercase
     * @see pro.respawn.kmmutils.inputforms.default.Rules.LowercaseOnly
     */
    @JvmInline
     value class NotLowercase(
        override val value: String,
    ) : ValidationError

    /**
     * Input's value is not uppercase
     * @see pro.respawn.kmmutils.inputforms.default.Rules.UppercaseOnly
     */
    @JvmInline
     value class NotUppercase(
        override val value: String,
    ) : ValidationError

    /**
     * Input's value has whitespace
     * @see pro.respawn.kmmutils.inputforms.default.Rules.NoWhitespace
     */
    @JvmInline
     value class HasWhitespace(
        override val value: String,
    ) : ValidationError

    /**
     * Input's value has newlines ('\n')
     * @see pro.respawn.kmmutils.inputforms.default.Rules.SingleLine
     */
    @JvmInline
     value class NotSingleline(
        override val value: String,
    ) : ValidationError

    /**
     * Input value has no uppercase letters
     * @see
     */
    @JvmInline
     value class NoUppercaseLetters(override val value: String) : ValidationError

    @Suppress("UndocumentedPublicClass") // what's here to document?
     companion object
}

class ValidationException(val errorList:List<ValidationError>):Exception(),List<ValidationError> by errorList

